package judger

import (
	"gugojudger/env"
	"gugojudger/utils/ojresult"
	"gugojudger/utils/stringutils"
	"io/ioutil"
	"os"
	"os/exec"
)

// StrCompiler 根据源代码进行编译
func StrCompiler(source string, LANG COMPILER) *ojresult.Result {
	result := ojresult.NewResult()
	filePath := randomDir()
	file, err := os.Create(filePath + "/Main" + addSuffix(LANG))
	if err != nil {
		result.SetMessage(AFG_IE, false)
		result.AddData("msg", err.Error())
		return result
	}
	file.Write([]byte(source))
	file.Close()

	switch LANG {
	case C_GCC:
		{
			result = compileGcc(filePath)
			break
		}
	default:
		{
			result = &ojresult.Result{Code: -0x20, Data: make(map[string]string)}
			break
		}
	}

	return result
}

//利用GCC进行代码的编译
func compileGcc(dirPath string) *ojresult.Result {
	result := ojresult.NewResult()

	cmd := exec.Command("gcc", dirPath+"/Main.c", "-o", dirPath+"/Main")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		result.SetMessage(AFG_IE, false)
		result.AddData("msg", err.Error())
		return result
	}
	defer func() {
		stdout.Close()
	}()

	stderr, err := cmd.StderrPipe()
	if err != nil {
		result.SetMessage(AFG_IE, false)
		result.AddData("msg", err.Error())
		return result
	}
	defer func() {
		stderr.Close()
	}()

	err = cmd.Start()
	if err != nil {
		result.SetMessage(AFG_IE, false)
		result.AddData("msg", err.Error())
		return result
	}

	//opOut,err := ioutil.ReadAll(stdout)
	//if err!= nil{
	//	result.SetMessage(AFG_IE,false)
	//	result.AddData("msg",err.Error())
	//	return result
	//}

	opErr, err := ioutil.ReadAll(stderr)
	if err != nil {
		result.SetMessage(AFG_IE, false)
		result.AddData("msg", err.Error())
		return result
	}
	cmd.Wait()
	if cmd.ProcessState.Success() {
		result.SetMessage(AFG_CC, true)
		result.AddData("msg", dirPath)
	} else {
		result.SetMessage(AFG_CE, false)
		result.AddData("msg", string(opErr))
	}

	return result
}

//生成随机的文件夹名称
func randomDir() string {
	str := env.GetWorkPath() + stringutils.RandomStr(10)
	err := os.Mkdir(str, 0777)
	if err != nil {
		return ""
	}
	return str
}

//根据代码类型添加文件的后缀名
func addSuffix(LANG COMPILER) string {
	switch LANG {
	case C_GCC, C_MINGW:
		return ".c"
	case CPP_GPP, CPP_MINGW:
		return ".cpp"
	case JAVA_JAVAC_1_8, JAVA_JAVAC_11:
		return ".java"
	case PYTHON_CPYTHON:
		return ".py"
	default:
		return ""
	}
}
